fdo#69984: Handle duplicate field names correctly.

Duplicate field names are represented in two ways: 1) 'Name' vs 'Name*' in
the UNO part of the pivot engine, and 2) Name,0 vs Name,1 which are a pair
of textural name and a numeric duplicate index in the non-UNO part of the
engine.  But some parts lost this duplicate index information and/or confused
the 2 ways of representation.  Hopefully this change will sort things out.

Change-Id: I03ae7b6c011c31ace454679837542d6d0909ecaa
diff --git a/sc/inc/dputil.hxx b/sc/inc/dputil.hxx
index 294ca97..e4ed831 100644
--- a/sc/inc/dputil.hxx
+++ b/sc/inc/dputil.hxx
@@ -26,7 +26,13 @@ public:

    SC_DLLPUBLIC static OUString getSourceDimensionName(const OUString& rName);

    static OUString createDuplicateDimensionName(const OUString& rOriginal, size_t nDupCount);
    /**
     * Get a duplicate index in case the dimension is a duplicate.  It returns
     * 0 in case it's an original dimension.
     */
    sal_uInt8 static getDuplicateIndex(const OUString& rName);

    SC_DLLPUBLIC static OUString createDuplicateDimensionName(const OUString& rOriginal, size_t nDupCount);

    static OUString getDateGroupName(
        sal_Int32 nDatePart, sal_Int32 nValue, SvNumberFormatter* pFormatter,
diff --git a/sc/inc/pivot.hxx b/sc/inc/pivot.hxx
index 6c9b03e..cd74a99 100644
--- a/sc/inc/pivot.hxx
+++ b/sc/inc/pivot.hxx
@@ -51,12 +51,14 @@
#include <com/sun/star/sheet/DataPilotFieldLayoutInfo.hpp>
#include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>

struct ScDPName
struct SC_DLLPUBLIC ScDPName
{
    OUString     maName;         ///< Original name of the dimension.
    OUString     maLayoutName;   ///< Layout name (display name)
    sal_uInt8 mnDupCount;

    explicit ScDPName(const OUString& rName, const OUString& rLayoutName);
    ScDPName();
    explicit ScDPName(const OUString& rName, const OUString& rLayoutName, sal_uInt8 nDupCount);
};

struct ScDPLabelData
@@ -69,6 +71,7 @@ struct ScDPLabelData
    sal_uInt16          mnFuncMask;     ///< Page/Column/Row subtotal function.
    sal_Int32           mnUsedHier;     ///< Used hierarchy.
    sal_Int32           mnFlags;        ///< Flags from the DataPilotSource dimension
    sal_uInt8           mnDupCount;
    bool                mbShowAll:1;    ///< true = Show all (also empty) results.
    bool                mbIsValue:1;    ///< true = Sum or count in data field.
    bool                mbDataLayout:1;
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index bab3988..4dca258 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -1840,10 +1840,16 @@ bool ScDPObject::FillLabelDataForDimension(
        xDimProp, OUString(SC_UNO_DP_FIELD_SUBTOTALNAME), OUString());

    bool bIsValue = true;                               //! check

    // Name from the UNO dimension object may have trailing '*'s in which
    // case it's a duplicate dimension. Convert that to a duplicate index.

    sal_uInt8 nDupCount = ScDPUtil::getDuplicateIndex(aFieldName);
    aFieldName = ScDPUtil::getSourceDimensionName(aFieldName);

    rLabelData.maName = aFieldName;
    rLabelData.mnCol = static_cast<SCCOL>(nDim);
    rLabelData.mnDupCount = nDupCount;
    rLabelData.mbDataLayout = bData;
    rLabelData.mbIsValue = bIsValue;

diff --git a/sc/source/core/data/dputil.cxx b/sc/source/core/data/dputil.cxx
index 40cfafb..e21b2a8 100644
--- a/sc/source/core/data/dputil.cxx
+++ b/sc/source/core/data/dputil.cxx
@@ -64,6 +64,27 @@ OUString ScDPUtil::getSourceDimensionName(const OUString& rName)
    return comphelper::string::stripEnd(rName, '*');
}

sal_uInt8 ScDPUtil::getDuplicateIndex(const OUString& rName)
{
    // Count all trailing '*'s.

    sal_Int32 n = rName.getLength();
    if (!n)
        return 0;

    sal_uInt8 nDupCount = 0;
    const sal_Unicode* p = rName.getStr();
    const sal_Unicode* pStart = p;
    p += n-1; // Set it to the last char.
    for (; p != pStart; --p, ++nDupCount)
    {
        if (*p != '*')
            break;
    }

    return nDupCount;
}

OUString ScDPUtil::createDuplicateDimensionName(const OUString& rOriginal, size_t nDupCount)
{
    if (!nDupCount)
diff --git a/sc/source/core/data/pivot2.cxx b/sc/source/core/data/pivot2.cxx
index bcdae43..bf779f9 100644
--- a/sc/source/core/data/pivot2.cxx
+++ b/sc/source/core/data/pivot2.cxx
@@ -58,10 +58,10 @@ bool equals(const DataPilotFieldReference& left, const DataPilotFieldReference& 

}

// ============================================================================
ScDPName::ScDPName() : mnDupCount(0) {}

ScDPName::ScDPName(const OUString& rName, const OUString& rLayoutName) :
    maName(rName), maLayoutName(rLayoutName) {}
ScDPName::ScDPName(const OUString& rName, const OUString& rLayoutName, sal_uInt8 nDupCount) :
    maName(rName), maLayoutName(rLayoutName), mnDupCount(nDupCount) {}

// ============================================================================

@@ -85,6 +85,7 @@ ScDPLabelData::ScDPLabelData() :
    mnFuncMask(PIVOT_FUNC_NONE),
    mnUsedHier(0),
    mnFlags(0),
    mnDupCount(0),
    mbShowAll(false),
    mbIsValue(false),
    mbDataLayout(false)
diff --git a/sc/source/ui/dbgui/pvfundlg.cxx b/sc/source/ui/dbgui/pvfundlg.cxx
index b1705da..40e431e 100644
--- a/sc/source/ui/dbgui/pvfundlg.cxx
+++ b/sc/source/ui/dbgui/pvfundlg.cxx
@@ -35,6 +35,7 @@
#include "dpsave.hxx"
#include "pvfundlg.hrc"
#include "globstr.hrc"
#include "dputil.hxx"

#include <vector>

@@ -574,8 +575,13 @@ void ScDPSubtotalOptDlg::FillLabelData( ScDPLabelData& rLabelData ) const
    else
        rLabelData.maSortInfo.Mode = DataPilotFieldSortMode::DATA;

    rLabelData.maSortInfo.Field = GetFieldName(maLbSortBy.GetSelectEntry());
    rLabelData.maSortInfo.IsAscending = maRbSortAsc.IsChecked();
    ScDPName aFieldName = GetFieldName(maLbSortBy.GetSelectEntry());
    if (!aFieldName.maName.isEmpty())
    {
        rLabelData.maSortInfo.Field =
            ScDPUtil::createDuplicateDimensionName(aFieldName.maName, aFieldName.mnDupCount);
        rLabelData.maSortInfo.IsAscending = maRbSortAsc.IsChecked();
    }

    // *** LAYOUT MODE ***

@@ -584,10 +590,15 @@ void ScDPSubtotalOptDlg::FillLabelData( ScDPLabelData& rLabelData ) const

    // *** AUTO SHOW ***

    rLabelData.maShowInfo.IsEnabled = maCbShow.IsChecked();
    rLabelData.maShowInfo.ShowItemsMode = maLbShowFromWrp.GetControlValue();
    rLabelData.maShowInfo.ItemCount = sal::static_int_cast<sal_Int32>( maNfShow.GetValue() );
    rLabelData.maShowInfo.DataField = GetFieldName(maLbShowUsing.GetSelectEntry());
    aFieldName = GetFieldName(maLbShowUsing.GetSelectEntry());
    if (!aFieldName.maName.isEmpty())
    {
        rLabelData.maShowInfo.IsEnabled = maCbShow.IsChecked();
        rLabelData.maShowInfo.ShowItemsMode = maLbShowFromWrp.GetControlValue();
        rLabelData.maShowInfo.ItemCount = sal::static_int_cast<sal_Int32>( maNfShow.GetValue() );
        rLabelData.maShowInfo.DataField =
            ScDPUtil::createDuplicateDimensionName(aFieldName.maName, aFieldName.mnDupCount);
    }

    // *** HIDDEN ITEMS ***

@@ -613,7 +624,7 @@ void ScDPSubtotalOptDlg::Init( const ScDPNameVec& rDataFields, bool bEnableLayou
    for( ScDPNameVec::const_iterator aIt = rDataFields.begin(), aEnd = rDataFields.end(); aIt != aEnd; ++aIt )
    {
        // Cache names for later lookup.
        maDataFieldNameMap.insert(NameMapType::value_type(aIt->maLayoutName, aIt->maName));
        maDataFieldNameMap.insert(NameMapType::value_type(aIt->maLayoutName, *aIt));

        maLbSortBy.InsertEntry( aIt->maLayoutName );
        maLbShowUsing.InsertEntry( aIt->maLayoutName );  // for AutoShow
@@ -714,10 +725,10 @@ void ScDPSubtotalOptDlg::InitHideListBox()
    maLbHide.Enable( bEnable );
}

const OUString& ScDPSubtotalOptDlg::GetFieldName(const OUString& rLayoutName) const
ScDPName ScDPSubtotalOptDlg::GetFieldName(const OUString& rLayoutName) const
{
    NameMapType::const_iterator itr = maDataFieldNameMap.find(rLayoutName);
    return itr == maDataFieldNameMap.end() ? rLayoutName : itr->second;
    return itr == maDataFieldNameMap.end() ? ScDPName() : itr->second;
}

sal_uInt16 ScDPSubtotalOptDlg::FindListBoxEntry(
@@ -728,8 +739,9 @@ sal_uInt16 ScDPSubtotalOptDlg::FindListBoxEntry(
    while (nPos < rLBox.GetEntryCount())
    {
        // translate the displayed field name back to its original field name.
        const OUString& rName = GetFieldName(rLBox.GetEntry(nPos));
        if (rName.equals(rEntry))
        ScDPName aName = GetFieldName(rLBox.GetEntry(nPos));
        OUString aUnoName = ScDPUtil::createDuplicateDimensionName(aName.maName, aName.mnDupCount);
        if (aUnoName.equals(rEntry))
        {
            bFound = true;
            break;
diff --git a/sc/source/ui/dbgui/pvlaydlg.cxx b/sc/source/ui/dbgui/pvlaydlg.cxx
index 4c30cb1..e4a9beb 100644
--- a/sc/source/ui/dbgui/pvlaydlg.cxx
+++ b/sc/source/ui/dbgui/pvlaydlg.cxx
@@ -60,6 +60,7 @@
#include "dpsave.hxx"
#include "dpshttab.hxx"
#include "scmod.hxx"
#include "dputil.hxx"

#include "sc.hrc"
#include "scabstdlg.hxx"
@@ -781,7 +782,7 @@ void ScPivotLayoutDlg::NotifyDoubleClick( ScPivotFieldType eType, size_t nFieldI
                    OUString aFuncStr = GetFuncString(nMask);
                    aLayoutName = aFuncStr + pDFData->maName;
                }
                aDataFieldNames.push_back(ScDPName(pDFData->maName, aLayoutName));
                aDataFieldNames.push_back(ScDPName(pDFData->maName, aLayoutName, pDFData->mnDupCount));
            }

            bool bLayout = (eType == PIVOTFIELDTYPE_ROW) &&
@@ -1584,7 +1585,9 @@ IMPL_LINK_NOARG(ScPivotLayoutDlg, OkHdl)

    for( ScDPLabelDataVector::const_iterator aIt = maLabelData.begin(), aEnd = maLabelData.end(); aIt != aEnd; ++aIt )
    {
        ScDPSaveDimension* pDim = aSaveData.GetExistingDimensionByName(aIt->maName);
        // "UNO" name may have trailing '*'s which signifies duplicate index.
        OUString aUnoName = ScDPUtil::createDuplicateDimensionName(aIt->maName, aIt->mnDupCount);
        ScDPSaveDimension* pDim = aSaveData.GetExistingDimensionByName(aUnoName);

        if (!pDim)
            continue;
diff --git a/sc/source/ui/inc/pvfundlg.hxx b/sc/source/ui/inc/pvfundlg.hxx
index 63cc80e..a89ab38 100644
--- a/sc/source/ui/inc/pvfundlg.hxx
+++ b/sc/source/ui/inc/pvfundlg.hxx
@@ -162,7 +162,7 @@ private:
    void                Init( const ScDPNameVec& rDataFields, bool bEnableLayout );
    void                InitHideListBox();

    const OUString& GetFieldName(const OUString& rLayoutName) const;
    ScDPName GetFieldName(const OUString& rLayoutName) const;

    /** Searches for a listbox entry, starts search at specified position. */
    sal_uInt16 FindListBoxEntry( const ListBox& rLBox, const OUString& rEntry, sal_uInt16 nStartPos ) const;
@@ -203,7 +203,7 @@ private:
    ScDPObject&         mrDPObj;            /// The DataPilot object (for member names).
    ScDPLabelData       maLabelData;        /// Cache for members data.

    typedef ::boost::unordered_map< OUString, OUString, OUStringHash > NameMapType;
    typedef ::boost::unordered_map<OUString, ScDPName, OUStringHash> NameMapType;
    NameMapType maDataFieldNameMap; /// Cache for displayed name to field name mapping.
};